
import numpy as np

import matplotlib.pyplot as plt

from view.endSrc.One2OneDistance import One2OneDistance
from view.endSrc.N2NDistances import N2NDistances
from view.endSrc.Dataset import Dataset
import math
from view.endSrc.MixedGaussianDatasetGenerator import MixedGaussianDatasetGenerator
import random
from view.endSrc.NodeSet import NodeSet

class MergeCenters:

    def __init__(self):
        self.dataset = None
        self.disMat = None
        self.threshold = None

    def _calThreshold(self):
        '''

        :return: threshold,which is mean of 50 percent of smallest distances
        '''
        n2n = N2NDistances()
        self.disMat = n2n(self.dataset)
        # dis = DataFrame(dis)
        disList = []
        n = len(self.dataset)
        for i in range(n):
            for j in range(n):
                if self.disMat[i, j] > 0.000001:
                    disList.append(self.disMat[i, j])
        disList.sort()
        small = []
        counts = math.floor(len(disList) * 0.05)
        for i in range(counts):
            small.append(disList[i])

        self.threshold =np.mean(small)


    def _mergeFollow(self, i, dataList, outputList):
        v = dataList[i]
        s = len(dataList)
        for j in range(i+1, s):
            other = dataList[j]
            if other is None:
                continue
            if v.distance(other) < self.threshold:
                m = v.merge(other)
                outputList.append(m)
                dataList[j] = None
                return True
        return False


    def _mergeAll(self, dataList, outputList):
        anyMerged = False
        for i, v in enumerate(dataList):
            if v is None:
                continue
            isMergedHappened = self._mergeFollow(i, dataList, outputList)
            if isMergedHappened:
                anyMerged = True
                continue
            outputList.append(v)

        return anyMerged



    def mergeCen(self, dataset):

        self.dataset = np.asarray(dataset)

        self._calThreshold()
        # ids = np.arange(len(dataset))
        # node = NodeSet(dataset, ids)
        size = len(dataset)
        dataList = []
        for i in range(size):
            n = NodeSet(dataset, [i])     ####
            dataList.append(n)
        outputList = []
        anyMergedHappened = True
        while anyMergedHappened:
            anyMergedHappened = self._mergeAll(dataList, outputList)
            if anyMergedHappened:
                dataList = outputList
                outputList = []

        merCen = []
        for point in dataList:
            for i in point.idList:
                merCen.append(point.dataset[i])
                break
        return merCen




    @staticmethod
    def test():
        # ps = []
        # for i in range(5):
        #     ps.append(random.uniform(1, 3))
        #
        # print(ps)
        # numOfInstances = 100
        # g = MixedGaussianDatasetGenerator(numOfInstances, numOfFeatures=2,
        #                                   overlap=1.5,
        #                                   paiList=ps,
        #                                   xRange=[10, 500])
        #
        # g.genSeparableComponents()  # generate mean and covariance   meanlist and varMatList
        # mDataset = g.genMixedDataset()
        # dataset = mDataset
        #
        # ids = np.arange(numOfInstances)
        dataset = [[ 2.33191725e+02,4.58582498e+02],
 [ 2.25331728e+02,4.75576908e+02],
 [ 2.45171253e+02,4.54911359e+02],
 [ 2.41730208e+02 ,4.59057314e+02],
 [ 2.53211009e+02,4.47512235e+02],
 [ 2.24621036e+02,4.73209608e+02],
 [ 2.46743324e+02,4.61674474e+02],
 [ 2.28922015e+02,4.65835532e+02],
 [ 2.43382016e+02 ,4.51533607e+02],
 [ 2.30616553e+02,4.65981555e+02],
 [ 2.41900704e+02,4.65275464e+02]]


        # p2p = One2OneDistance()
        # dataset = np.asarray(dataset)
        # labels = np.arange(len(dataset))
        #
        # plt.scatter(dataset[:, 0], dataset[:, 1],
        #             label='2D origin', c=labels, marker="+")
        # for i in range(len(dataset)):
        #     # plt.plot(meanList[i][0], meanList[i][1], c='r', marker='x')
        #     text = "c" + str(i)
        #     plt.annotate(text, xy=(dataset[i][0], dataset[i][1]),
        #                  xytext=(dataset[i][0], dataset[i][1]))
        #
        # plt.xlabel('x')
        # plt.ylabel('y')
        # plt.title('2D origin data')
        # plt.legend()
        # plt.show()

        megerCen =MergeCenters()

        points = megerCen.mergeCen(dataset)
        print(len(points))
        print('--mergerId--', points)
        # merCen = []
        # for point in points:
        #     for i in point.idList:
        #         merCen.append(point.dataset[i])
        #         break
        # print(merCen)
            # print(id.idList)

        # print('threshold: ', megerCen.threshold)
        # print('1-5: ', p2p(dataset[1], dataset[5]))
        # print('0-3: ', p2p(dataset[0], dataset[3]))
        # print('0-2: ', p2p(dataset[0], dataset[2]))
        #
        # print('3-6: ', p2p(dataset[3], dataset[6]))



if __name__ == '__main__':
    MergeCenters.test()

